#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <process.h>
#include <vector>

CRITICAL_SECTION g_cs;
HANDLE g_e; 
std::vector<char> g_v;

void tfunc(void* p)
{
    size_t* pn = (size_t*)p;

	EnterCriticalSection(&g_cs);
	std::cout << "thread[" << *pn << "]: ";
	std::vector<char>::iterator i = g_v.begin();
	do
	{
		std::cout << *i++ << "[" << *pn << "] ";

	}
	while(i != g_v.end());
	std::cout << std::endl;
	delete pn;

    LeaveCriticalSection(&g_cs);
}

void tf1(void* p)
{
	using namespace std;
	cout << "tf1 waiting for event to be set...\n";
	WaitForSingleObject(g_e, INFINITE);
	cout << "tf1 event arrived (!)\n";
}

void tf2(void* p)
{
	using namespace std;
	cout << "tf2 sleeping...\n";
	Sleep(5000);
	cout << "tf2 event signaled\n";
	SetEvent(g_e);
}

int main()
{
	using namespace std;
	
	InitializeCriticalSection(&g_cs);
	
	char ac[] = "abcdefghijklm";
	g_v.assign(ac, ac+strlen(ac));

	cout << "original vector contents: ";
	vector<char>::iterator i = g_v.begin();
	do
	{
		std::cout << *i++ << ' ';
	}
	while (i != g_v.end());
	cout << std::endl;

	cout << "1) critical section test\n";
	const int cnt = 2;
	HANDLE ht[cnt];
	using namespace std;
	cout << "creating thread" << endl;
	for (size_t ti = 0; ti < cnt; ++ti)
	{
		int* pn = new int(ti);
		ht[ti] = (HANDLE)_beginthread( tfunc, 0, pn);
	}

	cout << "waiting for threads execution final" << endl;
	WaitForMultipleObjects( cnt, ht, TRUE, INFINITE );
	cout << "threads finished, exiting" << endl;

	DeleteCriticalSection(&g_cs);
	
	cout << "2) events test\n";
	g_e = CreateEvent(  NULL, TRUE, TRUE, TEXT("event")); 
	ResetEvent(g_e);
	HANDLE ht1, ht2;
	cout << "creating threads" << endl;
	ht1 = (HANDLE)_beginthread( tf1, 0, 0);
	ht2 = (HANDLE)_beginthread( tf2, 0, 0);
	
	cout << "main waiting for event" << endl;
	WaitForSingleObject(g_e, INFINITE);
	cout << "main event arrived (!)" << endl;

	return 0;
}